home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Devices / Load PCI Driver / Load PCI Driver.c < prev    next >
Encoding:
Text File  |  1997-07-10  |  15.1 KB  |  528 lines  |  [TEXT/CWIE]

  1. /*
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **  Load PCI Driver Sample  
  5. **
  6. **    by Matthew Xavier Mora, Apple Developer Technical Support
  7. **
  8. **    File:        Load PCI DFriver.c
  9. **
  10. **    Copyright © 1996-1997 Apple Computer, Inc.
  11. **    All rights reserved.
  12. **
  13. **    You may incorporate this sample code into your applications without
  14. **    restriction, though the sample code has been provided "AS IS" and the
  15. **    responsibility for its operation is 100% yours.  However, what you are
  16. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  17. **    after having made changes. If you're going to re-distribute the source,
  18. **    we require that you make it clear in the source that the code was
  19. **    descended from Apple Sample Code, but that you've made changes.
  20. */
  21.  
  22. /*
  23. **
  24. ** This Code loads Wayne Flansburg PCI 'ndrv' so you can see it load without
  25. ** having to have a PCI card installed.
  26. ** This requires the PCI interfaces and libraries from ETO.
  27. **
  28. ** --------------------------------------
  29. **     Date        Author            Comments
  30. ** --------------------------------------
  31. ** 02-01-96        mxm                I wrote the first version in the "Writing PCI drivers" class. Got it to load
  32. **                                the sample driver I was writing. No real user interface
  33. **                                to speak of.
  34. **
  35. ** 03-25-97     mxm             Moved to a real app
  36. **                              Fixed the can't load the library a second time bug.
  37. **                              I was using HighestUnitNumber to get the unit number to load.
  38. **                              I thought this call found the last used unit number. It
  39. **                              actually expanded the unit table to the max number of 
  40. **                              entries! I put in MyFindSpaceInUnitTable routine and use it instead.
  41. **                              Fix crashing Malph by moving it into an application shell. I don't 
  42. **                              know why it would cause Malph to crash.
  43. **
  44. ** 03-28-97        mxm                Took out the MyFindSpaceInUnitTable routine. I wasn't using the 
  45. **                                InstallDriverFromFile correctly. HighestUnitNumber wasn't the problem.
  46. **                                That's what I get for trying to program without the Documentation.
  47. **                                Added Drag Manger and ODoOC support so you can drag a driver
  48. **                                into the window or on the application and it will load it.
  49. **                                 Display more info from the driver.
  50. ** 04-15-97        mxm                Cleaned it up for the Dev CD
  51. **
  52. ** 06-11-97        mxm             Fixed the error -2538 by passing nil for the regID.
  53. **
  54. */
  55.  
  56. //------------------------------------------------------------------
  57. #pragma mark Includes
  58. //------------------------------------------------------------------
  59.  
  60. #include <Devices.h>
  61. #include <NameRegistry.h>
  62. #include <StandardFile.h>
  63. #include <LowMem.h>
  64. #include <Dialogs.h>
  65. #include "SimpleApp.h"
  66. #include <stdio.h>
  67. #include <string.h>
  68.  
  69. //------------------------------------------------------------------
  70. #pragma mark Prototypes
  71. //------------------------------------------------------------------
  72.  
  73. pascal    OSErr    FSpGetFullPath(const FSSpec *spec, short *fullPathLength, Handle *fullPath);
  74.  
  75. //------------------------------------------------------------------
  76. #pragma mark Globals
  77. //------------------------------------------------------------------
  78.  
  79. short    gDrvrRefNum = 0; /* global variable for storing my driver reference number */
  80. long     gLoadButton;
  81. long    gUnloadButton;
  82. short     gVert;
  83. short    gLineHeight;
  84. NMRec    gAlertNMRec;
  85. Str255    gAlertStr = "\pAn error occurred. Please bring Matt's PCI Loader to the front.";
  86. short    gError = 0;
  87.  
  88. //------------------------------------------------------------------
  89. #pragma mark Defines
  90. //------------------------------------------------------------------
  91.  
  92. #define LMGetUnitTableEntryCount() (*((short *)0x1d2))
  93. #define LMSetUnitTableEntryCount(x) (*((short *)0x1d2) = (x))
  94.  
  95. #pragma mark -
  96.  
  97. //------------------------------------------------------------------
  98. static void AlertUser(short err)
  99. //------------------------------------------------------------------
  100. {
  101.     // in this case just set the global and the idle routine will display the error
  102.     gError = err;
  103. }
  104.  
  105. /*
  106. // I grabbed this code from somewhere
  107. //------------------------------------------------------------------
  108. static short MyFindSpaceInUnitTable(void)
  109. //------------------------------------------------------------------
  110. {
  111.     Ptr            curUTableBase, newUTableBase;
  112.     short            curUTableEntries, newUTableEntries;
  113.     short            refNum, unitNum;
  114.     
  115.     // get current unit table values from low memory globals 
  116.     curUTableEntries = LMGetUnitTableEntryCount();
  117.     curUTableBase     = LMGetUTableBase();
  118.     
  119.     // search for empty space in the current unit table 
  120.     for ( unitNum = curUTableEntries - 1; 
  121.             unitNum >= 48; // lowest available unit number 
  122.             unitNum-- )
  123.     {
  124.         refNum = ~(unitNum);
  125.         if (GetDCtlEntry(refNum) == nil)
  126.             return(unitNum); // found a space 
  127.     }
  128.     
  129.     
  130.     // no space in the current table, so make a new one 
  131.     
  132.     // increase the size of the table by 16 (an arbitrary value)
  133.     newUTableEntries = curUTableEntries + 16;
  134.     
  135.     // allocate space for the new table 
  136.     newUTableBase =  NewPtrSysClear((long)newUTableEntries * sizeof(Handle));
  137.     if (newUTableBase == nil) {
  138.         return(MemError());
  139.     }
  140.     // copy the old table to the new table 
  141.     BlockMoveData(curUTableBase, newUTableBase, (long)curUTableEntries * sizeof(Handle));
  142.     
  143.     // set the new unit table values in low memory 
  144.     LMSetUTableBase(newUTableBase);
  145.     LMSetUnitTableEntryCount( newUTableEntries);
  146.     
  147.     unitNum = newUTableEntries - 1;
  148.  
  149.     // unitNum = 0; //uh bad thing man.
  150.     return(unitNum); 
  151. }
  152.  
  153. */
  154.  
  155.  
  156. //------------------------------------------------------------------
  157. static void ForceUpdate(void)
  158. //------------------------------------------------------------------
  159. {
  160.     if (gSACurrentWindow) {
  161.         SetPort(gSACurrentWindow);
  162.         InvalRect(&gSACurrentWindow->portRect);
  163.     }    
  164. }
  165.  
  166. //------------------------------------------------------------------
  167. static void UnloadDriver(void)
  168. //------------------------------------------------------------------
  169. {
  170.     short err;
  171.     
  172.     if (gDrvrRefNum) { 
  173.         err = RemoveDriver(gDrvrRefNum, true);
  174.         gDrvrRefNum = 0;
  175.     }
  176. }
  177.  
  178. //------------------------------------------------------------------
  179. static short InstallDriver(FSSpecPtr spec) 
  180. //------------------------------------------------------------------
  181. {
  182.     RegEntryID             device={0,0};
  183.     short                 lowUnitNumber,hiUnitNumber ;    
  184.     short                 err = -1;    
  185.         
  186.     
  187.     if (gDrvrRefNum) {
  188.         UnloadDriver();
  189.     }
  190.      lowUnitNumber = 48 ; // MyFindSpaceInUnitTable();
  191.      hiUnitNumber = HighestUnitNumber();
  192.      
  193.     if (lowUnitNumber > 0) {
  194.     
  195.         err = InstallDriverFromFile(spec,nil,lowUnitNumber ,hiUnitNumber,&gDrvrRefNum);
  196.         if (err != noErr) {
  197.             AlertUser(err);  // we can be called from inside a drag handler so just set a flag
  198.             SAEnableObject(gLoadButton);
  199.             SADisableObject(gUnloadButton);
  200.         } else {
  201.             SAEnableObject(gUnloadButton);
  202.             SADisableObject(gLoadButton);
  203.         }
  204.     } 
  205.     ForceUpdate();
  206.     return err;    
  207. }
  208.  
  209. // Load a driver via StandardFile
  210. //------------------------------------------------------------------
  211. static    short LoadDriver(void)
  212. //------------------------------------------------------------------
  213. {
  214.  
  215.     short                 err = -1;
  216.  
  217.     OSType                 typeList[4];
  218.     OSType *            typeListPtr = typeList;
  219.     StandardFileReply     reply;
  220.  
  221.     
  222.     typeList[0] = 'ndrv';
  223.         
  224.     StandardGetFile(nil,1,typeList,&reply);
  225.     if (reply.sfGood) {
  226.         err = InstallDriver(&reply.sfFile);
  227.     }
  228.     
  229.     return err;    
  230. }
  231.  
  232. // ODOC handler
  233. //------------------------------------------------------------------
  234. static pascal OSErr     MyOpenFileProc(FSSpecPtr myFSSPtr)
  235. //------------------------------------------------------------------
  236. {
  237.     short err;
  238.     
  239.     err =  InstallDriver(myFSSPtr) ;
  240.     return noErr;
  241. }
  242.  
  243.  
  244. //------------------------------------------------------------------
  245. static    pascal short DoIdle(EventRecord *evt)
  246. //------------------------------------------------------------------
  247. {
  248.         Str255 tempStr;    
  249.         short err;
  250. #pragma unused (evt)
  251.     // in case we want to do something at idle time
  252.     
  253.     if (gError) {
  254.         gAlertNMRec.qType         = nmType;
  255.         gAlertNMRec.nmFlags        = 0;
  256.         gAlertNMRec.nmPrivate    = 0;
  257.         gAlertNMRec.nmReserved    = 0;
  258.         gAlertNMRec.nmResp         = nil;
  259.         gAlertNMRec.nmStr         = gAlertStr;
  260.         gAlertNMRec.nmSound     = nil;
  261.         gAlertNMRec.nmMark         = 1;
  262.         gAlertNMRec.nmIcon         = nil;
  263.         err = AEInteractWithUser(kAEDefaultTimeout,&gAlertNMRec,nil);    
  264.         
  265.         NumToString(gError,tempStr);
  266.         ParamText(tempStr,"\p","\p","\p");
  267.         Alert(1002,nil);
  268.         gError = 0;
  269.     }
  270.     return noErr;
  271. }
  272.  
  273. //------------------------------------------------------------------
  274.     static    pascal short DoLoadDriver(ButtonItemRef me,long refCon)
  275. //------------------------------------------------------------------
  276. {
  277. #pragma unused (me,refCon)
  278.     short err;
  279.     
  280.     err = LoadDriver();
  281.     if (err == noErr ) {
  282.         SADisableMe();
  283.         SAEnableObject(gUnloadButton);
  284.         ForceUpdate();
  285.     }
  286.     return noErr;
  287. }
  288.  
  289. //------------------------------------------------------------------
  290.     static    pascal short DoUnloadDriver(ButtonItemRef me,long refCon)
  291. //------------------------------------------------------------------
  292. {
  293. #pragma unused (me,refCon)
  294.  
  295.     UnloadDriver();
  296.     SADisableMe();
  297.     SAEnableObject(gLoadButton);
  298.     ForceUpdate();
  299.     
  300.     return noErr;
  301. }
  302.  
  303. //------------------------------------------------------------------
  304.     static GetLineHeight(void)
  305. //------------------------------------------------------------------
  306. {
  307.     FontInfo info;
  308.     
  309.     GetFontInfo(&info);
  310.     return (info.ascent + info.descent + info.leading);
  311. }
  312.  
  313. //------------------------------------------------------------------
  314.     static void DrawItem(StringPtr label,StringPtr text)
  315. //------------------------------------------------------------------
  316. {
  317.         DrawString (label);
  318.         DrawString (text);
  319.         MoveTo(5,gVert);
  320.         gVert += gLineHeight; 
  321. }
  322.  
  323. //------------------------------------------------------------------
  324.     static void DrawHex(StringPtr label,long n)
  325. //------------------------------------------------------------------
  326. {
  327.         char s[256];
  328.         
  329.         sprintf(s,"%0X",n);
  330.         DrawString (label);
  331.         DrawText(s,0,strlen(s));
  332.         MoveTo(5,gVert);
  333.         gVert += gLineHeight; 
  334. }
  335.  
  336. //------------------------------------------------------------------
  337.     static void DrawHandle(StringPtr label,Handle text)
  338. //------------------------------------------------------------------
  339. {
  340.     DrawString (label);
  341.     if (text) {
  342.         DrawText (*text,0,GetHandleSize(text));
  343.     }
  344.     MoveTo(5,gVert);
  345.     gVert += gLineHeight; 
  346. }
  347.  
  348. //------------------------------------------------------------------
  349.     static void DrawNumber(StringPtr label,long n)
  350. //------------------------------------------------------------------
  351. {    
  352.     Str255 tempStr;
  353.  
  354.     NumToString(n,tempStr);
  355.     DrawString (label);
  356.     DrawString (tempStr);
  357.     MoveTo(5,gVert);
  358.     gVert += gLineHeight; 
  359. }
  360.  
  361. //------------------------------------------------------------------
  362.     static    pascal short MyUpdate(long refCon)
  363. //------------------------------------------------------------------
  364. {
  365. #pragma unused (refCon)
  366.     Str255                 tempStr;
  367.     UnitNumber             unitNum;
  368.     DriverFlags         flags;
  369.     DriverOpenCount     count;
  370.     RegEntryID             device;
  371.     CFragHFSLocator     driverLoadLocation;
  372.     CFragConnectionID     fragmentConnID;
  373.     DriverEntryPointPtr fragmentMain;
  374.     DriverDescription     driverDesc;
  375.     FSSpec                fileSpec;
  376.     Handle                 fullPath = nil;
  377.     short                 err    = 0;
  378.     short                fullPathLength;
  379.     
  380.     gLineHeight = GetLineHeight();
  381.     
  382.     gVert = 120;
  383.     MoveTo(5,gVert);
  384.     gVert += gLineHeight; 
  385.     
  386.     if (gDrvrRefNum) {
  387.     
  388.         DrawString("\pThe driver is loaded. refNum = (");
  389.         NumToString(gDrvrRefNum,tempStr);
  390.         DrawString (tempStr);
  391.         DrawString("\p)");
  392.         MoveTo(5,gVert);
  393.         
  394.         gVert += gLineHeight; 
  395.         driverLoadLocation.u.onDisk.fileSpec = &fileSpec;
  396.         err =  GetDriverInformation(gDrvrRefNum,
  397.                                     &unitNum, 
  398.                                     &flags, 
  399.                                     &count,
  400.                                     tempStr, 
  401.                                     &device,
  402.                                     &driverLoadLocation,
  403.                                     &fragmentConnID,
  404.                                     &fragmentMain, 
  405.                                     &driverDesc);
  406.         
  407.         DrawItem("\pName: ",tempStr);
  408.         DrawNumber("\pUnitNumber: ",unitNum);    
  409.         DrawNumber("\pCount: ",count);
  410.         DrawHex("\pflags: ",flags);
  411.  
  412.         err = FSpGetFullPath(&fileSpec,&fullPathLength, &fullPath);
  413.         if (fullPath) {
  414.             DrawHandle("\pPath: ",fullPath);
  415.             DisposeHandle(fullPath);
  416.         }    
  417.         DrawHex("\pFragment Main: 0x",(long)fragmentMain);        
  418.     } else {
  419.         DrawString("\pNo Driver Loaded.             ");
  420.     }
  421.     
  422.     return noErr;
  423. }
  424.  
  425. //---------------------------------------------------------------------------------------
  426.     static pascal OSErr MyPutData (ObjectItemRef orh,OSType kind,Ptr  data,long len,long flags)
  427. //---------------------------------------------------------------------------------------
  428. {
  429. #pragma unused (orh,len,flags)
  430.  
  431.     HFSFlavor * theFile;
  432.     
  433.     if (kind == flavorTypeHFS) { 
  434.         theFile = (HFSFlavor *)data;
  435.         
  436.         if (theFile->fileType == 'cfrg' ) {
  437.             InstallDriver(&theFile->fileSpec);
  438.         }
  439.     }
  440.  
  441.  
  442.     return noErr;
  443. }
  444.  
  445.  
  446. // The drag receive handler
  447. //------------------------------------------------------------------
  448. static pascal short MyReceive(ObjectItemRef orh,DragReference theDrag)
  449. //------------------------------------------------------------------
  450. {
  451. #pragma unused(orh)
  452.     ItemReference    itemRef;
  453.     Size            dataSize;
  454.     HFSFlavor        theHFSFlavor;
  455.     OSErr            retCode;
  456.  
  457.  
  458.     // There is only one item, so get its reference number.
  459.     retCode = GetDragItemReferenceNumber(theDrag, 1, &itemRef);
  460.     
  461.     if (retCode == noErr) {
  462.         dataSize = sizeof(HFSFlavor);
  463.         retCode = GetFlavorData(theDrag, itemRef, flavorTypeHFS, &theHFSFlavor, &dataSize, 0);
  464.         if (retCode == noErr)  {
  465.             InstallDriver(&theHFSFlavor.fileSpec) ;
  466.         }
  467.  
  468.     }
  469.     return retCode;
  470. }
  471.  
  472. //------------------------------------------------------------------
  473. void main(void)
  474. //------------------------------------------------------------------
  475.     long     buttonID     = 1;
  476.     long     textID         = 2;
  477.     long    dragID         = 3;
  478.     Str255     tempStr;
  479.     Rect    r ;
  480.     long     gMyWindowID;
  481.     short    err;
  482.     
  483.     InitSimpleApp(2,kUseStandardMenu);      // Simple App Sets up the Tool Box For us 
  484.     gMyWindowID = GetDocumentWindow (128);     // Get our stored window 
  485.     SetOpenFileProc (MyOpenFileProc);        // set open file proc. This is called on an ODOC event
  486.     
  487.     SetWTitle(gSACurrentWindow,"\pMatt's PCI Driver Loader");
  488.     
  489.     InstallIdleProc(DoIdle);
  490.     SetWindowUpdateProc(gSACurrentWindow,MyUpdate );     //gSACurrentWindow for now, its a Kludge
  491.     GetIndString(tempStr,kStaticStrings,kButtonName);    // Get button name
  492.  
  493.     SetRectDimensions(&r, 180, 20);            // This Sets its size without changing it position
  494.     SetRectLocation(&r, 10, 30);            // This Sets a rects anchor point
  495.     (void)InstallPushButton(&buttonID,gSACurrentWindow,tempStr,&r,0,DoLoadDriver,nil);
  496.     gLoadButton = buttonID;
  497.     OffsetRect(&r,200,0);
  498.     GetIndString(tempStr,kStaticStrings,3);    // Get button name
  499.     (void)InstallPushButton(&buttonID,gSACurrentWindow,tempStr,&r,0,DoUnloadDriver,nil);
  500.     gUnloadButton = buttonID;
  501.     SADisableMe();
  502.     
  503.     
  504.     SetRect(&r,4,55,gSACurrentWindow->portRect.right - 4,110);        
  505.     GetIndString(tempStr,kStaticStrings,kAboutText);    // Get about this snippet text
  506.     (void)InstallStaticText(&textID,gSACurrentWindow,tempStr,&r);    
  507.     
  508.     // lets add drag and drop support for our window    
  509.     err = InstallDragObject(&dragID,gSACurrentWindow,"\p",&gSACurrentWindow->portRect, nil, nil, MyReceive, 0);
  510.     err = SAInstallStandardDragHandlers(gSACurrentWindow);              // enable dragging
  511.     err = SAAddWindowDragDataTypes(gSACurrentWindow,flavorTypeHFS);        // we accept flavorTypeHFS
  512.  
  513.     Run();                                                                 //Let SimpleApp handle the rest
  514.         
  515.     // lets check and see if the driver is still loaded and ask the 
  516.     // user what to do if it is loaded
  517.     if (gDrvrRefNum) {
  518.         short itemHit;
  519.  
  520.         itemHit = Alert(1001,nil);
  521.         if (itemHit == 1 ) {
  522.             UnloadDriver();
  523.         }
  524.     }
  525. }
  526.  
  527.